<template>
  <view class="webview-container">
    <web-view
      ref="webview"
      :src="webviewUrl"
      @error="handleError"
    ></web-view>
  </view>
</template>

<script>
import { generateUUID } from '@/utils/common.js'
import { acceptCall, hangupCall, sendOffer, sendAnswer, sendIceCandidate } from '@/api/im/videocall.js'
// 导入 URLSearchParams polyfill（兼容微信小程序）
import { getURLSearchParams } from '@/utils/url-search-params-polyfill.js'

export default {
  name: 'WebViewPage',
  data() {
    return {
      webviewUrl: '',
      title: '加载中...',
      handlerId: null, // WebSocket监听器ID
      callId: null, // 当前通话ID（从页面参数获取）
      targetId: null, // 目标用户ID（从页面参数获取）
      mainFrame: null, // H5环境下的frame引用
      postMsg: null, // 消息发送方法引用
      processedMessageIds: new Set(), // 存储已处理的消息ID，防止重复处理
      messageIdExpireTime: 5 * 60 * 1000 // 消息ID过期时间（毫秒），避免内存无限增长
    }
  },
  onLoad(options) {
    // 处理 token 参数（用于 H5 独立运行时的身份验证）
    if (options.token) {
      console.log('收到 token 参数，设置本地存储', options.token);
      uni.setStorageSync('token', options.token);
    }

    // 处理租户ID参数（用于跨租户支持）
    if (options.tenantId) {
      console.log('收到 tenantId 参数，设置本地存储', options.tenantId);
      uni.setStorageSync('tenantId', options.tenantId);
    }

    // 处理 currentUserId 参数（用于 WebSocket 消息判断）
    if (options.currentUserId) {
      console.log('收到 currentUserId 参数，设置本地存储', options.currentUserId);
      uni.setStorageSync('userId', options.currentUserId);
    }

    // 获取传入的URL和标题
    if (options.url) {
      this.webviewUrl = decodeURIComponent(options.url);
    }
    if (options.title) {
      this.title = decodeURIComponent(options.title);
      // 设置页面标题
      uni.setNavigationBarTitle({
        title: this.title
      });
    }

    // 如果是通话页面，构建hybrid URL
    if (options.targetId && (options.callType === '0' || options.callType === '1')) {
      this.buildCallUrl(options);
      // 保存通话ID和目标用户ID
      this.callId = options.callId;
      this.targetId = options.targetId;
    }

    // 生成WebSocket监听器ID
    this.handlerId = generateUUID();
    this.registerWebSocketHandler();

    // #ifdef H5
    setTimeout(() => {
      const frames = document.getElementsByTagName('iframe');
      if (frames && frames.length > 0) {
        this.mainFrame = frames[0].contentWindow;
      }
      this.postMsg = this.h5sendH5;
    }, 500);

    window.onmessage = (e) => {
      this.msgCallback(e);
    }
    // #endif
  },
  onReady() {
    // 页面渲染完成
  },
  onShow() {
    // 页面显示时的逻辑
  },

  onHide() {
    // 页面隐藏时的逻辑
  },
  onUnload() {
    // 页面卸载时清理消息监听器
    window.onmessage = null;
    this.unregisterWebSocketHandler();

    // 清理已处理消息记录，防止内存泄漏
    if (this.processedMessageIds) {
      this.processedMessageIds.clear();
    }
  },
  methods: {
    // 构建通话页面URL
    buildCallUrl(options) {
      try {
        // 配置STUN服务器
        const stunConfig = {
          stun: [
            'turn:47.109.42.217:3478',
          ],
          stunUser: 'admin',
          stunPass: '123123'
        };

        // 根据是否为来电设置不同的状态参数
        const isIncomingCall = options.isIncomingCall === 'true';
        const statusParams = isIncomingCall ? {
          status: '3',          // status=3 表示来电中状态
          // 不设置calling参数，避免自动启动媒体流
        } : {
          status: '1',          // status=1 表示拨打电话状态
          calling: '1'          // calling=1 表示直接拨打，自动启动媒体流
        };

        // 构建hybrid页面URL，使用正确的参数名
        const URLSearchParamsClass = getURLSearchParams();
        const params = new URLSearchParamsClass({
          target_id: options.targetId,
          name: options.name || '用户',
          avatar: options.avatar,
          call_id: options.callId || '', // 通话ID
          stun: encodeURIComponent(JSON.stringify(stunConfig)),
          platform: 'app',
          type: options.callType,     // type=1 表示视频通话，type=0 表示语音通话
          ...statusParams         // 展开状态参数
        });

        const hybridUrl = `/hybrid/html/index.html?${params.toString()}`;
        this.webviewUrl = decodeURIComponent(hybridUrl);

        console.log('构建的通话URL:', this.webviewUrl);
      } catch (error) {
        console.error('构建通话URL失败:', error);
        uni.showToast({
          title: '通话启动失败',
          icon: 'none'
        });
      }
    },

    // 处理来自webview的消息
    msgCallback(e) {
      try {
        const message = e.data;

        // 检查UniApp标准消息格式
        if (message.type === 'WEB_INVOKE_APPSERVICE' && message.data) {
          const actualData = message.data;

          // 检查postMessage调用，真正的数据在arg中
          if (actualData.name === 'postMessage' && actualData.arg) {
            const realMessage = actualData.arg;

            console.log('向webview发送消息:', realMessage);

            // 处理各种消息类型
            if (realMessage.type === 'close' || realMessage.type === 'call-ended') {
              uni.navigateBack();
            } else if (realMessage.event === 'hangup') {
              this.handleHangupCall();
            } else if (realMessage.event === 'acceptRtc') {
              this.handleAcceptCall(realMessage);
            } else if (realMessage.event === 'offer') {
              this.handleOffer(realMessage);
            } else if (realMessage.event === 'answer') {
              this.handleAnswer(realMessage);
            } else if (realMessage.event === 'iceCandidate') {
              this.handleIceCandidate(realMessage);
            } else if (realMessage.event === 'streamTimeout') {
              this.handleStreamTimeout(realMessage);
            }
          }
        }
      } catch (error) {
        console.error('处理WebView消息失败:', error);
      }
    },





    // 处理webview加载错误
    handleError(event) {
      console.error('WebView加载错误:', event);
      uni.showModal({
        title: '加载失败',
        content: '页面加载失败，请检查网络连接',
        showCancel: false,
        success: () => {
          uni.navigateBack();
        }
      });
    },

    // H5端向webview发送消息
    h5sendH5(params) {
      if (this.mainFrame) {
        this.mainFrame.postMessage(params, '*');
      }
    },

    // 向webview发送消息
    sendMessageToWebView(message) {
      try {
        if (this.postMsg) {
          this.postMsg(message);
        }
        console.log('向webview发送消息:', message);
      } catch (error) {
        console.error('向webview发送消息失败:', error);
      }
    },

    // 注册WebSocket消息监听器
    registerWebSocketHandler() {
      if (this.handlerId && this.$webSocketManager) {
        console.log('注册WebSocket监听器:', this.handlerId);
        this.$webSocketManager.addListener(this.handlerId, this.handleWebSocketMessage);
      }
    },

    // 移除WebSocket消息监听器
    unregisterWebSocketHandler() {
      if (this.handlerId && this.$webSocketManager) {
        console.log('移除WebSocket监听器:', this.handlerId);
        this.$webSocketManager.removeListener(this.handlerId);
      }
    },

    // 生成消息唯一标识键
    generateMessageKey(message) {
      try {
        // 消息类型
        const type = message.type || 'unknown';

        // 解析content获取会话ID
        let callId = '';

        if (message.content) {
          try {
            const content = typeof message.content === 'string'
              ? JSON.parse(message.content)
              : message.content;

            // 获取通话/会话ID
            callId = content.callId || '';
          } catch (parseError) {
            console.error('解析消息content失败:', parseError);
          }
        }

        // 生成唯一键：类型_会话ID
        return `${type}_${callId}`;
      } catch (error) {
        console.error('生成消息键失败:', error);
        // 如果生成键失败，使用随机数确保不重复
        return `fallback_${Date.now()}_${Math.random()}`;
      }
    },

    /**
     * 标记消息为已处理
     * @param {String} messageId 消息ID
     */
    markMessageAsProcessed(messageId) {
      // 添加到已处理集合
      this.processedMessageIds.add(messageId);

      // 设置定时器，5分钟后自动清除该消息ID，防止内存无限增长
      setTimeout(() => {
        this.processedMessageIds.delete(messageId);
        console.log('已清除过期消息ID:', messageId);
      }, this.messageIdExpireTime);

      console.log('消息已标记为已处理:', messageId);
      console.log('当前已处理消息数量:', this.processedMessageIds.size);
    },

    // 处理WebSocket消息
    handleWebSocketMessage(message) {
      try {
        console.log('WebView页面收到WebSocket消息:', message);

        // ICE候选消息不需要去重，因为WebRTC连接过程中会产生多个ICE候选
        const isIceMessage = message.type === 'video.call.ice';

        if (!isIceMessage) {
          // 生成消息唯一标识，用于防止重复处理
          const messageId = this.generateMessageKey(message);

          // 检查是否已处理过此消息
          if (this.processedMessageIds.has(messageId)) {
            console.log('消息已处理，跳过:', messageId);
            return;
          }

          // 标记消息为已处理
          this.markMessageAsProcessed(messageId);
        }

        let webViewMessage = null;
        try {
          // 解析消息内容
          const content = typeof message.content === 'string'
              ? JSON.parse(message.content)
              : message.content;

          // 将解析后的内容转发给webview
          webViewMessage = {
            msgType: message.type,
            ...content
          };
        } catch (error) {
          console.error('解析消息失败:', error);
        }

        message = webViewMessage;

        // 根据消息类型进行特殊处理
        if (message.msgType) {
          switch (message.msgType) {
            case 'video.call.invite':
              // 处理视频通话邀请
              this.handleVideoCallInvite(message);
              break;
            case 'video.call.accept':
              // 处理接受通话
              this.handleVideoCallAccept(message);
              break;
            // 注意：挂断消息现在由中转页面 video-call-transfer/index.vue 处理
            case 'video.call.offer':
              // 处理WebRTC Offer信令
              this.handleVideoCallOffer(message);
              break;
            case 'video.call.answer':
              // 处理WebRTC Answer信令
              this.handleVideoCallAnswer(message);
              break;
            case 'video.call.ice':
              // 处理ICE候选信令
              this.handleVideoCallIceCandidate(message);
              break;
            default:
              // 处理其他类型消息
              console.log('收到其他类型WebSocket消息:', message.type);
              break;
          }
        }
      } catch (error) {
        console.error('处理WebSocket消息失败:', error);
      }
    },

    // 处理视频通话邀请
    handleVideoCallInvite(message) {
      console.log('处理视频通话邀请:', message);
      // 可以在这里添加视频通话邀请的特殊处理逻辑
    },

    // 处理接受通话
    handleVideoCallAccept(message) {
      console.log('DEBUG:处理接受通话:', message);

      // 将WebSocket消息转发给webview，让webview处理RTC连接
      const webViewMessage = {
        event: 'acceptRtc', // webview期望的事件类型
        ...message // 包含其他消息数据
      };
      this.sendMessageToWebView(webViewMessage);
    },

    // 处理WebRTC Offer信令
    handleVideoCallOffer(message) {
      console.log('处理WebRTC Offer信令:', message);
      // 转发给webview处理
      const webViewMessage = {
        event: 'offer',
        sdp: message.sdp.sdp
      };
      this.sendMessageToWebView(webViewMessage);
    },

    // 处理WebRTC Answer信令
    handleVideoCallAnswer(message) {
      console.log('处理WebRTC Answer信令:', message);
      // 转发给webview处理
      const webViewMessage = {
        event: 'answer',
        sdp: message.sdp.sdp
      };
      this.sendMessageToWebView(webViewMessage);
    },

    // 处理ICE候选信令
    handleVideoCallIceCandidate(message) {
      console.log('处理ICE候选信令:', message);
      // 转发给webview处理
      const webViewMessage = {
        event: 'iceCandidate',
        iceCandidate: message.candidate
      };
      this.sendMessageToWebView(webViewMessage);
    },

    // 处理接听通话事件
    async handleAcceptCall(message) {
      try {
        console.log('处理接听通话事件:', message);

        // 使用页面参数传入的通话ID
        let callId = this.callId;

        if (!callId) {
          console.error('无法获取通话ID，无法接听通话');
          uni.showToast({
            title: '接听失败，缺少通话ID',
            icon: 'none'
          });
          return;
        }

        console.log('正在接听通话:', callId);

        // 显示加载提示
        uni.showLoading({
          title: '接听中...',
          mask: true
        });

        // 调用后端接口接听通话
        const result = await acceptCall(callId);

        uni.hideLoading();

        if (result) {
          console.log('接听通话成功:', result);

          uni.showToast({
            title: '接听成功',
            icon: 'success'
          });
        } else {
          throw new Error('接听失败');
        }
      } catch (error) {
        console.error('接听通话失败:', error);

        uni.hideLoading();

        uni.showToast({
          title: error.message || '接听失败',
          icon: 'none'
        });
      }
    },

    // 处理 WebRTC Offer 信令
    async handleOffer(message) {
      try {
        console.log('处理 Offer 信令:', message);

        // 使用页面参数传入的通话ID
        let callId = this.callId;

        if (!callId) {
          console.error('无法获取通话ID，无法发送Offer');
          return;
        }

        if (!message.sdp) {
          console.error('Offer 消息缺少 SDP 数据');
          return;
        }

        // 构建SDP数据
        const sdpData = {
          type: 'offer',
          sdp: message.sdp
        };

        console.log('发送 Offer 信令到后端:', {
          callId: callId,
          toUserId: parseInt(this.targetId),
          toUserType: 1,
          sdp: sdpData
        });

        // 调用专门的Offer接口
        const result = await sendOffer(callId, parseInt(this.targetId), 1, sdpData);
        console.log('Offer 信令发送成功:', result);

      } catch (error) {
        console.error('处理 Offer 信令失败:', error);
      }
    },

    // 处理 WebRTC Answer 信令
    async handleAnswer(message) {
      try {
        console.log('处理 Answer 信令:', message);

        // 使用页面参数传入的通话ID
        let callId = this.callId;

        if (!callId) {
          console.error('无法获取通话ID，无法发送Answer');
          return;
        }

        if (!message.sdp) {
          console.error('Answer 消息缺少 SDP 数据');
          return;
        }

        // 构建SDP数据
        const sdpData = {
          type: 'answer',
          sdp: message.sdp
        };

        console.log('发送 Answer 信令到后端:', {
          callId: callId,
          toUserId: parseInt(this.targetId),
          toUserType: 1,
          sdp: sdpData
        });

        // 调用专门的Answer接口
        const result = await sendAnswer(callId, parseInt(this.targetId), 1, sdpData);
        console.log('Answer 信令发送成功:', result);

      } catch (error) {
        console.error('处理 Answer 信令失败:', error);
      }
    },

    // 处理 ICE 候选信令
    async handleIceCandidate(message) {
      try {
        console.log('处理 ICE 候选信令:', message);

        // 使用页面参数传入的通话ID
        let callId = this.callId;

        if (!callId) {
          console.error('无法获取通话ID，无法发送ICE候选');
          return;
        }

        if (!message.iceCandidate) {
          console.error('ICE 候选消息缺少候选数据');
          return;
        }

        // ICE候选数据可能是字符串或对象
        let candidateData = message.iceCandidate;
        if (typeof candidateData === 'string') {
          try {
            candidateData = JSON.parse(candidateData);
          } catch (err) {
            console.error('解析ICE候选数据失败:', err);
            return;
          }
        }

        console.log('发送 ICE 候选到后端:', {
          callId: callId,
          toUserId: parseInt(this.targetId),
          toUserType: 1,
          candidate: candidateData
        });

        // 调用专门的ICE候选接口
        const result = await sendIceCandidate(callId, parseInt(this.targetId), 1, candidateData);
        console.log('ICE 候选发送成功:', result);

      } catch (error) {
        console.error('处理 ICE 候选信令失败:', error);
      }
    },

    // 处理挂断通话事件
    async handleHangupCall(message = {}) {
      try {
        console.log('处理挂断通话事件:', message);

        // 使用页面参数传入的通话ID
        let callId = this.callId;

        if (callId) {
          console.log('正在挂断通话:', callId);

          // 调用后端接口挂断通话
          try {
            const result = await hangupCall(callId);
            console.log('挂断通话成功:', result);
          } catch (error) {
            console.error('挂断通话失败:', error);
            // 挂断失败不阻止页面返回
          }
        }

      } catch (error) {
        console.error('处理挂断事件失败:', error);
      }
    },

    // 处理视频流连接超时
    handleStreamTimeout(message) {
      try {
        console.log('收到视频流连接超时消息:', message);

        // 显示系统繁忙提示
        uni.showModal({
          title: '连接失败',
          content: message.message || '系统繁忙，稍后再试',
          showCancel: false,
          confirmText: '确定',
          success: () => {
            // 返回聊天页面
            uni.navigateBack({
              fail: () => {
                // 如果无法返回，则跳转到首页
                uni.switchTab({
                  url: '/pages/index/index'
                })
              }
            })
          }
        });

      } catch (error) {
        console.error('处理视频流超时事件失败:', error);

        // 即使出错也要返回上一页
        uni.navigateBack({
          fail: () => {
            uni.switchTab({
              url: '/pages/index/index'
            })
          }
        })
      }
    }
  }
}
</script>

<style scoped>
.webview-container {
  width: 100%;
  height: 100vh;
}
</style>
